﻿/********************************************************8
 *	Author: Andrew Deren
 *	Date: July, 2004
 *	http://www.adersoftware.com
 * 
 *	StringTokenizer class. You can use this class in any way you want
 * as long as this header remains in this file.
 * 
 **********************************************************/
using System;
using System.IO;
using System.Text;

namespace java.util
{
    public class StringTokenizer : IEnumeration<Object>
    {

        private String str;

        private String delimiters;

        private int position;

        /**
         * Constructs a new {@code StringTokenizer} for the parameter string using
         * whitespace as the delimiter. The {@code returnDelimiters} flag is set to
         * {@code false}.
         * 
         * @param string
         *            the string to be tokenized.
         */
        public StringTokenizer(String str)
            : this(str, " \t\n\r\f")
        { //$NON-NLS-1$
        }

        /**
         * Constructs a new {@code StringTokenizer} for the parameter string using
         * the specified delimiters. The {@code returnDelimiters} flag is set to
         * {@code false}. If {@code delimiters} is {@code null}, this constructor
         * doesn't throw an {@code Exception}, but later calls to some methods might
         * throw a {@code NullPointerException}.
         * 
         * @param string
         *            the string to be tokenized.
         * @param delimiters
         *            the delimiters to use.
         */
        public StringTokenizer(String str, String delimiters)
        {
            if (str != null)
            {
                this.str = str;
                this.delimiters = delimiters;
                this.position = 0;
            }
            else
                throw new NullReferenceException("input string is null");
        }

        /**
         * Constructs a new {@code StringTokenizer} for the parameter string using
         * the specified delimiters, returning the delimiters as tokens if the
         * parameter {@code returnDelimiters} is {@code true}. If {@code delimiters}
         * is null this constructor doesn't throw an {@code Exception}, but later
         * calls to some methods might throw a {@code NullPointerException}.
         * 
         * @param string
         *            the string to be tokenized.
         * @param delimiters
         *            the delimiters to use.
         * @param returnDelimiters
         *            {@code true} to return each delimiter as a token.
         */
        //public StringTokenizer(String str, String delimiters,
        //        bool returnDelimiters)
        //{
        //    if (str != null)
        //    {
        //        this.str = str;
        //        this.delimiters = delimiters;
        //        this.returnDelimiters = returnDelimiters;
        //        this.position = 0;
        //    }
        //    else
        //        throw new NullReferenceException("input string is null");
        //}

        /**
         * Returns the number of unprocessed tokens remaining in the string.
         * 
         * @return number of tokens that can be retreived before an {@code
         *         Exception} will result from a call to {@code nextToken()}.
         */
        public int countTokens()
        {
            int count = 0;
            bool inToken = false;
            for (int i = position, length = str.Length; i < length; i++)
            {
                if (delimiters.IndexOf(str[i], 0) >= 0)
                {
                    if (inToken)
                    {
                        count++;
                        inToken = false;
                    }
                }
                else
                {
                    inToken = true;
                }
            }
            if (inToken)
                count++;
            return count;
        }

        /**
         * Returns {@code true} if unprocessed tokens remain. This method is
         * implemented in order to satisfy the {@code Enumeration} interface.
         * 
         * @return {@code true} if unprocessed tokens remain.
         */
        public bool HasMoreElements()
        {
            return HasMoreTokens();
        }

        /**
         * Returns {@code true} if unprocessed tokens remain.
         * 
         * @return {@code true} if unprocessed tokens remain.
         */
        public bool HasMoreTokens()
        {
            if (delimiters == null)
            {
                throw new NullReferenceException("delimiters is null");
            }
            int length = str.Length;
            if (position < length)
            {

                // find a character which is not a delimiter
                for (int i = position; i < length; i++)
                    if (delimiters.IndexOf(str[i], 0) == -1)
                        return true;
            }
            return false;
        }

        /**
         * Returns the next token in the string as an {@code Object}. This method is
         * implemented in order to satisfy the {@code Enumeration} interface.
         * 
         * @return next token in the string as an {@code Object}
         * @throws NoSuchElementException
         *                if no tokens remain.
         */
        public Object NextElement()
        {
            return NextToken();
        }

        /**
         * Returns the next token in the string as a {@code String}.
         * 
         * @return next token in the string as a {@code String}.
         * @throws NoSuchElementException
         *                if no tokens remain.
         */
        public String NextToken()
        {
            if (delimiters == null)
            {
                throw new NullReferenceException("Delimiter is not set");
            }
            int i = position;
            int length = str.Length;

            if (i < length)
            {
                while (i < length && delimiters.IndexOf(str[i], 0) >= 0)
                    i++;
                position = i;
                if (i < length)
                {
                    for (position++; position < length; position++)
                        if (delimiters.IndexOf(str[position], 0) >= 0)
                            return str.Substring(i, position - i);
                    return str.Substring(i);
                }
            }
            throw new Exception("NoSuchElementException");
        }

        /**
         * Returns the next token in the string as a {@code String}. The delimiters
         * used are changed to the specified delimiters.
         * 
         * @param delims
         *            the new delimiters to use.
         * @return next token in the string as a {@code String}.
         * @throws NoSuchElementException
         *                if no tokens remain.
         */
        public String NextToken(String delims)
        {
            this.delimiters = delims;
            return NextToken();
        }
    }
}
